package com.lnj.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 导入LambdaQueryWrapper
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lnj.api.FileUploadApi;
import com.lnj.api.IdGeneratorApi;
import com.lnj.bean.dto.CategoryDTO;
import com.lnj.bean.model.Category;
import com.lnj.product.mapper.CategoryMapper;
import com.lnj.product.service.CategoryService;
import com.lnj.product.utils.JsonUtil;
import com.lnj.utils.RedisKeys;
import com.lnj.utils.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
// 导入 Spring Cache 注解
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
// import org.springframework.cache.annotation.CachePut; // 在更新单个对象时也可能用到

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 商品分类服务实现类
 */
@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private IdGeneratorApi idGeneratorApi;
    @Autowired
    private FileUploadApi fileUploadApi;
    // 注入RedisTemplate
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private JsonUtil jsonUtil;

    /**
     * 新增类别
     * @param categoryDTO 待新增的类别信息
     * @return 新增成功后的类别DTO
     */
    @Override
    @Transactional
    // 新增类别会导致所有类别列表和单个类别缓存失效，所以清除整个 'category' 缓存空间
    @CacheEvict(value = "category", allEntries = true)
    public CategoryDTO addCategory(CategoryDTO categoryDTO) {
        // 1. 生成类别ID
        ResponseResult rr= this.idGeneratorApi.getNextId();
        if(  rr.getCode()!=1){
            throw new RuntimeException("类别ID生成失败");
        }
        Long categoryId =Long.parseLong(rr.getData().toString());
        categoryDTO.setCategoryId(categoryId);

        // 2. 模拟图标上传并设置URL
        ResponseResult rr2= this.fileUploadApi.upload(   new MultipartFile[]{ categoryDTO.getIconFile() });
        if (rr2.getCode() == 0) {
            // 部分成功 - data是拼接的字符串
            String resultData = rr2.getData().toString();
            // 解析出URL部分（假设格式为"url,url失败:xxx"）
            String[] parts = resultData.split("失败:");
            if (parts.length > 0 && !parts[0].isEmpty()) {
                String[] urls = parts[0].split(",");
                if (urls.length > 0) {
                    categoryDTO.setIcon(urls[0]); // 取第一个URL
                }
            }
            // 抛出异常包含失败信息
            throw new RuntimeException("图片上传部分失败: " + (parts.length > 1 ? parts[1] : "未知原因"));
        } else if (rr2.getCode()==2){
            // 全部失败 - data是失败信息字符串
            throw new RuntimeException("图片上传失败: " + rr2.getData());
        }
        List<String> mainImages= (List<String>) rr2.getData();
        categoryDTO.setIcon(   mainImages.get(0)  );
        // 3. 设置默认状态为正常
        if (categoryDTO.getCategoryStatus() == null) {
            categoryDTO.setCategoryStatus(1); // 默认正常
        }
        // 4. 将DTO转换为实体
        Category category = new Category();
        BeanUtils.copyProperties(categoryDTO, category);
        // 5. 插入数据库
        int result = categoryMapper.insert(category);
        if (result > 0) {
            // 插入成功后，返回包含完整信息的DTO
            BeanUtils.copyProperties(category, categoryDTO);
            String categoryJson = jsonUtil.toJson(categoryDTO);
            // 添加到Redis缓存
            String categoryKey = RedisKeys.CATEGORY_INFO + categoryId;
            stringRedisTemplate.opsForValue().set(categoryKey, categoryJson);
            return categoryDTO;
        } else {
            throw new RuntimeException("新增类别失败");
        }
    }

    /**
     * 查询所有类别
     * @return 所有类别DTO的列表
     * @param categoryStatus
     */
    @Override
    // 缓存所有类别列表：
    // value = "category": 缓存名称
    // key = "#categoryStatus != null ? 'list_status_' + #categoryStatus : 'list_all'":
    // 根据传入的 categoryStatus 参数动态生成缓存key。
    // 如果 categoryStatus 不为 null，则键为 "list_status_X" (例如 "list_status_1")
    // 如果 categoryStatus 为 null，则键为 "list_all" (查询所有状态的类别)
    @Cacheable(value = "category", key = "#categoryStatus != null ? 'list_status_' + #categoryStatus : 'list_all'")
    public List<CategoryDTO> getAllCategories(Integer categoryStatus) {
        System.out.println("从数据库中查询类别列表，状态：" + (categoryStatus == null ? "所有" : categoryStatus)); // 方便观察是否命中缓存
        // 查询所有未被删除的类别 (categoryStatus = 1)
        // 注意：这里使用 LambdaUpdateWrapper 进行查询是不常见的，通常查询用 LambdaQueryWrapper
        // 如果你的意图是查询，应使用 LambdaQueryWrapper
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        if(categoryStatus!=null){
            queryWrapper.eq(Category::getCategoryStatus, categoryStatus); // 只查询指定状态的类别
        }
        List<Category> categories = categoryMapper.selectList(queryWrapper);
        // 将实体列表转换为DTO列表
        List<CategoryDTO> categoryDTOList = categories.stream()
                .map(category -> {
                    CategoryDTO dto = new CategoryDTO();
                    BeanUtils.copyProperties(category, dto);
                    return dto;
                })
                .collect(Collectors.toList());

        return categoryDTOList;
    }

    /**
     * 修改类别状态
     * @param categoryId 类别ID
     * @return 是否设置成功
     */
    @Override
    @Transactional
    // 修改类别状态后，所有类别列表缓存和单个类别缓存都可能失效，所以清除整个 'category' 缓存空间
    @CacheEvict(value = "category", allEntries = true)
    public boolean setCategoryStatusToHidden(Long categoryId, Integer categoryStatus) {
        // 构建更新条件，只更新状态
        LambdaUpdateWrapper<Category> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Category::getCategoryId, categoryId)
                .set(Category::getCategoryStatus, categoryStatus); // 设置新状态

        int result = categoryMapper.update(null, updateWrapper);

        // 清除Redis中相关的缓存
        if (result > 0) {
            // 删除单个类别缓存
            stringRedisTemplate.delete(RedisKeys.CATEGORY_INFO + categoryId);
            // 删除所有类别列表缓存

        }

        return result > 0;
    }

    /**
     * 更新类别信息
     * @param categoryDTO 待更新的类别信息
     * @return 更新成功后的类别DTO
     */
    @Override
    @Transactional
    // 更新类别后，所有类别列表缓存和单个类别缓存都可能失效，所以清除整个 'category' 缓存空间
    @CacheEvict(value = "category", allEntries = true)
    public CategoryDTO updateCategory(CategoryDTO categoryDTO) {
        if (categoryDTO.getCategoryId() == null) {
            throw new IllegalArgumentException("类别ID不能为空，无法更新");
        }

        // 模拟图标上传并设置URL (如果图标数据有变化)
        if( categoryDTO.getIconFile()!=null ) {
            ResponseResult rr2 = this.fileUploadApi.upload(new MultipartFile[]{categoryDTO.getIconFile()});
            if (rr2.getCode() == 0) {
                // 部分成功 - data是拼接的字符串
                String resultData = rr2.getData().toString();
                // 解析出URL部分（假设格式为"url,url失败:xxx"）
                String[] parts = resultData.split("失败:");
                if (parts.length > 0 && !parts[0].isEmpty()) {
                    String[] urls = parts[0].split(",");
                    if (urls.length > 0) {
                        categoryDTO.setIcon(urls[0]); // 取第一个URL
                    }
                }
                // 抛出异常包含失败信息
                throw new RuntimeException("图片上传部分失败: " + (parts.length > 1 ? parts[1] : "未知原因"));
            } else if (rr2.getCode()==2){
                // 全部失败 - data是失败信息字符串
                throw new RuntimeException("图片上传失败: " + rr2.getData());
            }
            List<String> mainImages = (List<String>) rr2.getData();
            categoryDTO.setIcon(mainImages.get(0));
        }

        // 将DTO转换为实体
        Category category = new Category();
        BeanUtils.copyProperties(categoryDTO, category);

        // 执行更新，MyBatis Plus会根据实体中的@TableId注解自动识别主键
        int result = categoryMapper.updateById(category);
        if (result > 0) {
            // 清除Redis中相关的缓存
            stringRedisTemplate.delete(RedisKeys.CATEGORY_INFO + categoryDTO.getCategoryId());

            // 更新成功后，返回最新的类别信息
            CategoryDTO updatedCategory = getCategoryById(categoryDTO.getCategoryId());

            // 更新Redis缓存
            String categoryKey = RedisKeys.CATEGORY_INFO + categoryDTO.getCategoryId();
            String categoryJson = jsonUtil.toJson(updatedCategory);
            stringRedisTemplate.opsForValue().set(categoryKey, categoryJson);

            return updatedCategory;
        } else {
            throw new RuntimeException("类别更新失败，类别ID: " + categoryDTO.getCategoryId());
        }
    }

    /**
     * 根据ID获取类别详情
     * @param categoryId 类别ID
     * @return 类别DTO
     */
    @Override
    // 缓存单个类别：
    // value = "category": 缓存名称
    // key = "'id_' + #categoryId": 缓存键为 "id_" 加上具体的 categoryId (例如 "id_123")
    //@Cacheable(value = "category", key = "'id_' + #categoryId")
    public CategoryDTO getCategoryById(Long categoryId) {

        // 先从Redis缓存中获取
        String categoryKey = RedisKeys.CATEGORY_INFO + categoryId;
        String json = stringRedisTemplate.opsForValue().get(categoryKey);

        if (json != null) {
           log.info("从Redis缓存中获取类别ID: " + categoryId);
            CategoryDTO categoryDTO = jsonUtil.fromJson(json,CategoryDTO.class);
            return categoryDTO;
        }

        // Redis中没有则从数据库查询
        log.info("从数据库中查询类别ID: " + categoryId);
        Category category = categoryMapper.selectById(categoryId);
        if (category == null) {
            return null;
        }
        CategoryDTO dto = new CategoryDTO();
        BeanUtils.copyProperties(category, dto);

        // 将查询结果存入Redis缓存
        String categoryJson = jsonUtil.toJson(dto);
        stringRedisTemplate.opsForValue().set(categoryKey, categoryJson);

        return dto;
    }
}